package com.tqjc.system.core.gate.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef;
import com.tqjc.system.common.constant.ConfigConstant;
import com.tqjc.system.common.constant.GlobalConstant;
import com.tqjc.system.common.constant.HttpsConstant;
import com.tqjc.system.common.constant.SQLConstant;
import com.tqjc.system.common.entity.VO.VideoVO;
import com.tqjc.system.common.enums.GateRecordStatusEnum;
import com.tqjc.system.core.gate.asyn.CarPhotoThread;
import com.tqjc.system.core.gate.constants.GateConstant;
import com.tqjc.system.core.gate.sdk.callback.IPlateCallback;
import com.tqjc.system.core.gate.sdk.api.IceSdk;
import com.tqjc.system.core.gate.service.SysGateService;
import com.tqjc.system.core.threadpool.ThreadPoolManager;
import com.tqjc.system.core.util.HttpsUtils;
import com.tqjc.system.core.util.MyStringUtils;
import com.tqjc.system.system.dao.SysGateRecordDao;
import com.tqjc.system.system.entity.SysConfigEntity;
import com.tqjc.system.system.entity.SysGateRecordEntity;
import com.tqjc.system.system.service.SysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.List;


/**
 * @author 86195
 * @version 1.0
 * @description TODO
 * @date 2023/9/19 15:34
 */
@Service
@Slf4j
public class SysGateServiceImpl implements SysGateService {

    private static final int cameraNum = 6;
    private static Pointer[] sdk = new Pointer[cameraNum];

    private static WinDef.HWND[] hvideo = new WinDef.HWND[cameraNum];

    private static boolean[] bVideo = new boolean[cameraNum];

    @Autowired
    private IPlateCallback callback;

    @Autowired
    private SysGateRecordDao sysGateRecordDao;

    @Autowired
    private SysConfigService sysConfigService;

    private int carEnterGapTime;


    @Override
    public void init() {
        IceSdk.jnaLib.ICE_IPCSDK_Init();//initialization

        //初始化摄像头IP配置常量类
        //道闸名称与摄像头IP对应关系
        List<SysConfigEntity> gateNameList = sysConfigService.getConfigInfoByType(ConfigConstant.CONFIG_TYPE_CAMERA_GATENAME_IP);

        gateNameList.forEach( e ->{
            //key:ip   value:闸道名
            GateConstant.GATE_NAME_MAP.put(e.getConfigId(),e.getConfigValue());
        });
        //设备下标与摄像头IP对应关系
        List<SysConfigEntity> indexList = sysConfigService.getConfigInfoByType(ConfigConstant.CONFIG_TYPE_CAMERA_INDEX_IP);

        //其余配置信息
        SysConfigEntity configInfo = sysConfigService.getConfigInfo(ConfigConstant.CONFIG_TYPE_GATE_INFO, ConfigConstant.CONFIG_ID_CAR_ENTER_GAP_TIME);

        carEnterGapTime = Integer.valueOf(configInfo.getConfigValue());

        sdk[0] = null;
        sdk[1] = null;
        sdk[2] = null;
        sdk[3] = null;
        sdk[4] = null;
        sdk[5] = null;

        //相机连接
        for (SysConfigEntity sysConfigEntity : indexList) {
            String gateName = GateConstant.GATE_NAME_MAP.get(sysConfigEntity.getConfigId());
            List list = GateConstant.GATE_NAME_RELATION_INDEX_MAP.get(gateName);
            if(list == null){
                list = new ArrayList<>();
                list.add(Integer.valueOf(sysConfigEntity.getConfigValue()));
            } else {
                list.add(Integer.valueOf(sysConfigEntity.getConfigValue()));

            }
            GateConstant.GATE_NAME_RELATION_INDEX_MAP.put(gateName,list);
            connect(Integer.valueOf(sysConfigEntity.getConfigValue()),sysConfigEntity.getConfigId());
        }

    }





    private void connect(int index,String ip) {
        if (null != sdk[index]){
            //JOptionPane.showMessageDialog(demo, "相机已连接", "info",JOptionPane.WARNING_MESSAGE);
            return;
        }
        sdk[index] = IceSdk.jnaLib.ICE_IPCSDK_OpenDevice(ip);

        if (null == sdk[index]){
            log.error("ip:{}相机连接失败",ip);
            //JOptionPane.showMessageDialog(demo, "相机连接失败", "error",JOptionPane.WARNING_MESSAGE);
            return;
        }
        IceSdk.jnaLib.ICE_IPCSDK_EnableUTF8(sdk[index], 1);
        IceSdk.jnaLib.ICE_IPCSDK_SetPlateCallback(sdk[index], callback, index);
        log.info("ip:{}相机连接成功",ip);

    }






    /**
     * 断开连接
     */
    public void disconnect(){
        for(int i=0;i < cameraNum;i++){
            IceSdk.jnaLib.ICE_IPCSDK_Close(sdk[i]);
            bVideo[i] = false;
        }
        IceSdk.jnaLib.ICE_IPCSDK_Fini();
    }

    @Override
    public void monitor() {
        VideoVO videoVO = new VideoVO();
        //videoVO.addWindowListener(new MyListener());
        hvideo[0] = createHWNDByComponent(videoVO.getPanel_video1());
        hvideo[1] = createHWNDByComponent(videoVO.getPanel_video2());
        hvideo[2] = createHWNDByComponent(videoVO.getPanel_video3());
        hvideo[3] = createHWNDByComponent(videoVO.getPanel_video4());
        hvideo[4] = createHWNDByComponent(videoVO.getPanel_video5());
        hvideo[5] = createHWNDByComponent(videoVO.getPanel_video6());

        for(int i = 0;i < cameraNum;i++){
            bVideo[i] = video(i);
        }

    }


    private boolean video(int index) {
        if (null == sdk[index]){
            log.info("{}:相机未连接",index);
            return false;
        }

        if (!bVideo[index]){
            int iRet = IceSdk.jnaLib.ICE_IPCSDK_StartStream(sdk[index], 1, hvideo[index]);
            if (1 != iRet){
                //JOptionPane.showMessageDialog(demo, "Start video failed", "error",JOptionPane.WARNING_MESSAGE);
                return false;
            }
        }
        log.info("相机已打开");
        return true;

    }


    public class MyListener implements WindowListener {

        @Override
        public void windowActivated(WindowEvent arg0) {
            // TODO Auto-generated method stub

        }

        @Override
        public void windowClosed(WindowEvent arg0) {
            // TODO Auto-generated method stub

        }

        @Override
        public void windowClosing(WindowEvent arg0) {
            // TODO Auto-generated method stub
            log.info("窗口关闭");
            for (int i = 0; i < cameraNum; i++) {
                if (null != sdk[i]) {
                    bVideo[i] = false;
                    IceSdk.jnaLib.ICE_IPCSDK_StopStream(sdk[i]);
                }
            }

        }

        @Override
        public void windowDeactivated(WindowEvent arg0) {
            // TODO Auto-generated method stub

        }

        @Override
        public void windowDeiconified(WindowEvent arg0) {
            // TODO Auto-generated method stub

        }

        @Override
        public void windowIconified(WindowEvent arg0) {
            // TODO Auto-generated method stub

        }

        @Override
        public void windowOpened(WindowEvent arg0) {
            // TODO Auto-generated method stub
        }

    }


    @Override
    public void openGate(int index) throws Exception {
        if (null == sdk[index]){
            throw new Exception("打开道闸时，摄像头未连接");
        }
        int iRet = IceSdk.jnaLib.ICE_IPCSDK_OpenGate(sdk[index]);
        if (1 != iRet){
            throw new Exception("打开道闸失败");
        }
    }


    private WinDef.HWND createHWNDByComponent(Panel panel) {
        // TODO Auto-generated method stub
        return new WinDef.HWND(Native.getComponentPointer(panel));
    }

    @Override
    public synchronized void enter(SysGateRecordEntity entity) throws Exception {


        //1.先查两分钟内，数据库是否存在。存在不再插入数据
        LocalDateTime now = LocalDateTime.now();
        //识别到的车牌号码
        String carLicense = entity.getCarLicense();
        //车辆将要进入的道闸名
        String gateName = entity.getGateName();
        LocalDateTime paramDate = now.minus(carEnterGapTime, ChronoUnit.MINUTES);
        SysGateRecordEntity sysGateRecord = sysGateRecordDao.selectOne(new LambdaQueryWrapper<SysGateRecordEntity>()
                .eq(SysGateRecordEntity::getCarLicense, carLicense)
                //.eq(SysGateRecordEntity::getStatus,GateRecordStatusEnum.STATUS_ENTER.getStatus())
                .ge(SysGateRecordEntity::getCreateDate, paramDate).last(SQLConstant.SQL_LIMIT_1));


        List<Integer> gateIndexs = GateConstant.GATE_NAME_RELATION_INDEX_MAP.get(gateName);
        for (Integer index : gateIndexs) {
            this.openGate(index);
        }

        if(sysGateRecord == null){
            entity.setStatus(GateRecordStatusEnum.STATUS_DOING.getStatus());
            sysGateRecordDao.insert(entity);
            StringBuilder sb = new StringBuilder();
            carLicense = MyStringUtils.buildStrByCharLenth(10, MyStringUtils.getCharactersLength(carLicense), carLicense);
            String id = String.valueOf(entity.getIdKey());
            id = MyStringUtils.buildStrByCharLenth(32,MyStringUtils.getCharactersLength(id),id);
            gateName = MyStringUtils.buildStrByCharLenth(8,MyStringUtils.getCharactersLength(gateName),gateName);


//            carLicense = String.format("%-" + 10 + "s", carLicense);
//            id = String.format("%-" + 32 + "s", id);
//            gateName = String.format("%-" + 8 + "s", gateName);
            String param = sb.append(carLicense).append(id).append(gateName).toString();
            //发送车牌信息至TMS系统
            HttpsUtils.sendTMSPost(HttpsConstant.URL_SEND_CARNO,param);
        } else {
            //存在记录，判断其状态
            String status = sysGateRecord.getStatus();
            if(GateRecordStatusEnum.STATUS_DOING.getStatus().equals(status)){
                log.info("该车牌记录正在检验中，请稍等。无后续处理");
                return;
            }
            if(GateRecordStatusEnum.STATUS_ENTER.getStatus().equals(status)){
                //记录已被检验通过，继续打开道闸
                log.info("该车牌记录已被检验通过，继续打开道闸");
                //List<Integer> gateIndexs = GateConstant.GATE_NAME_RELATION_INDEX_MAP.get(gateName);
                for (Integer index : gateIndexs) {
                    this.openGate(index);
                }
                return;
            }
        }



    }

    @Override
    public synchronized void exit(SysGateRecordEntity entity) throws Exception {
        //1.先查询出来
        String carLicense = entity.getCarLicense();
        String gateName = entity.getGateName();
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime paramDate = now.minus(1, ChronoUnit.DAYS);
        //判断数据是否存在未出闸的记录
        SysGateRecordEntity sysGateRecord = sysGateRecordDao.selectOne(new LambdaQueryWrapper<SysGateRecordEntity>()
                .eq(SysGateRecordEntity::getCarLicense, carLicense)
                .eq(SysGateRecordEntity::getStatus, GateRecordStatusEnum.STATUS_ENTER.getStatus())
                .ge(SysGateRecordEntity::getCreateDate, paramDate).last(SQLConstant.SQL_LIMIT_1));
        List<Integer> gateIndexs = GateConstant.GATE_NAME_RELATION_INDEX_MAP.get(gateName);
        if(sysGateRecord != null){
            //存在记录
            log.info("更新当天车的离厂时间");
            entity.setStatus(GateRecordStatusEnum.STATUS_EXIT.getStatus());
            SysGateRecordEntity updateEntity = SysGateRecordEntity.builder().idKey(sysGateRecord.getIdKey())
                    .status(GateRecordStatusEnum.STATUS_EXIT.getStatus()).exitTime(new Date()).build();
            sysGateRecordDao.updateById(updateEntity);
            for (Integer index : gateIndexs) {
                this.openGate(index);
            }
            return;
        }
//        SysGateRecordEntity recordEntity = sysGateRecordDao.selectOne(new LambdaQueryWrapper<SysGateRecordEntity>()
//                .eq(SysGateRecordEntity::getCarLicense, carLicense)
//                .eq(SysGateRecordEntity::getStatus,GateRecordStatusEnum.STATUS_ENTER.getStatus())
//                .orderByDesc(SysGateRecordEntity::getCreateDate)
//                .last(SQLConstant.SQL_LIMIT_1));
//        if(recordEntity != null){
//            //更新离厂数据   照片与路径
//            sysGateRecordDao.update(null,new LambdaUpdateWrapper<SysGateRecordEntity>()
//                    .eq(SysGateRecordEntity::getCarLicense,carLicense).set(SysGateRecordEntity::getExitTime,LocalDateTime.now())
//                    .set(SysGateRecordEntity::getStatus, GateRecordStatusEnum.STATUS_EXIT.getStatus()));
//            String gateName = entity.getGateName();
//            //2.成功则打开道闸
//            List<Integer> gateIndexs = GateConstant.GATE_NAME_RELATION_INDEX_MAP.get(gateName);
//            for (Integer index : gateIndexs) {
//                this.openGate(index);
//            }
//        }
        //2.成功则打开道闸
        for (Integer index : gateIndexs) {
            this.openGate(index);
        }

        //ThreadPoolManager.INSTANCE.execute(new CarPhotoThread(sysGateRecordDao,entity));
    }

    /**
     * 参数补齐
     * @param param  实际入参
     * @param num  入参总位数要求
     * @return   组装成要求的入参参数
     */
    private String buildParamStr(String param,int num){
        if(StringUtils.isEmpty(param)){
            return null;
        }
        StringBuilder sb = new StringBuilder();
        int length = param.length();
        for(int i = 0;i < num - length; i++ ){
            sb.append(" ");
        }
        sb.append(param);
        return sb.toString();
    }

}
